<?php

/**
 * @property-read string $Name
 * @property-read ProductItem[] $ProductItems
 * @property-read int $TotalCost
 * @property-read bool IsEmpty
 */
class ShoppingCart
{
    /** @var string */
    protected $name = 'No Name';

    /** @var ProductItem[] */
    protected $productItems = array();

    /** @var ShoppingCart */
    protected static $instance;

    /**
     * @return ShoppingCart
     */
    protected function __construct()
    {
    }

    /**
     * @param string $name
     * @return mixed
     * @throws Exception
     */
    public function __get($name)
    {
        switch ($name) {
            case 'Name':
                return $this->name;
            case 'ProductItems':
                return $this->productItems;
            case 'TotalCost':
                $totalCost = 0;

                $productItems = $this->productItems;
                foreach ($productItems as $productItem) {
                    $totalCost += $productItem->TotalCost;
                }

                return $totalCost;
            case 'IsEmpty':
                if (count($this->productItems) == 0) {
                    return true;
                } else {
                    return false;
                }
            default:
                throw new Exception("cannot get $name property");
        }
    }

    /**
     * @param string $name
     * @param mixed $value
     * @throws Exception
     */
    public function __set($name, $value)
    {
        switch ($name) {
            case 'Name':
                $this->name = $value;
                break;
            default:
                throw new Exception("cannot set $name property");
        }
    }

    /**
     * @param $productItemID
     * @return ProductItem
     */
    public function getProductItem($productItemID)
    {
        foreach ($this->productItems as $productItem) {
            if ($productItemID == $productItem->ID) {
                return $productItem;
            }
        }

        return null;
    }

    /**
     * @param int $productID
     * @return bool
     */
    public function addProductItem($productID)
    {
        $productPOJO = Application_Model_Product::getProduct($productID);
        if ($productPOJO == null) {
            return false;
        }

        // Nếu sản phẩm đã có trong giỏ hàng => thêm số lượng
        $numberOfProductItems = count($this->productItems);
        for ($i = 0; $i < $numberOfProductItems; $i++) {
            if ($productID == $this->productItems[$i]->ID) {
                $this->productItems[$i]->Amount++;
                return true;
            }
        }

        // Nếu chưa có thì add vào giỏ hàng và set amount = 1
        $productItem = new ProductItem(
            $productPOJO->ID, $productPOJO->Name, $productPOJO->Image,
            $productPOJO->NewPrice, 1
        );
        array_push($this->productItems, $productItem);

        return true;
    }

    /**
     * @param int $productItemID
     * @return bool
     */
    public function deleteProductItem($productItemID)
    {
        foreach ($this->productItems as $key => $productItem) {
            if ($productItemID == $productItem->ID) {
                unset($this->productItems[$key]);
                return true;
            }
        }

        return false;
    }

    /**
     * @param int $productItemID
     * @param int $productAmount
     * @return bool
     */
    public function editAmountProductItem($productItemID, $productAmount)
    {
        foreach ($this->productItems as $productItem) {
            if ($productItemID == $productItem->ID) {
                $productItem->Amount = $productAmount;
                return true;
            }
        }

        return false;
    }

    /**
     * @return ShoppingCart
     */
    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new ShoppingCart();
        }

        return self::$instance;
    }
}
